"""
@author: xiangping
@contact: xiangpingbu@gmail.com
@time: 2019/12/28 5:40 下午
@file: gaolu_controller.py
@Desc:
"""
import datetime
import json
import re
from typing import List

from flask import Blueprint, request, current_app

from app.controllers.response.response import SuccessResult
from app.database import convert
from app.models.po.gaolu.gaolu_predict_po import GaoLuPredictPO
from app.services.business import gaolu_biz_service
from app.services.business.gaolu_biz_service import gaolu_history_between, \
    param_dist_dict, param_quantile_dict, gaolu_lose_status_percentage, auto_score
from app.services.business.gaolu_biz_service import get_daily_score, get_ban_bie_score, gaolu_query_models, \
    get_gaolu_history_between, gaolu_history_data_transform
from app.utils import string_util
from app.utils.sys_utils import get_time_round_and_adjust, GaoLuEncoder

bp = Blueprint('gaolu', __name__, url_prefix="/api/v1/gaolu")
gaolu_bp = bp


@gaolu_bp.route('/GaoluResultBetween/', methods=['GET'])
def gaolu_result_between():
    start = request.args.get('start')
    end = request.args.get('end')
    ret = gaolu_history_between(start, end, left="close", right="close")
    return SuccessResult(detail=ret)


@gaolu_bp.route('/gaoLuParamDist', methods=['GET'])
def gaolu_param_dist():
    """
    提取各参数历史分布
    想要自主用start 和 end 选取时间段，必须设置refresh = True
    :return:
    """
    start = request.args.get('start')
    end = request.args.get('end')
    refresh = request.args.get('refresh')

    if string_util.is_not_empty(start) and string_util.is_not_empty(end):
        start = datetime.datetime.strptime(start, "%Y-%m-%d %H:%M:%S")
        end = datetime.datetime.strptime(end, "%Y-%m-%d %H:%M:%S")
    else:
        start = None
        end = None

    ret_dict = param_dist_dict(start, end, refresh)
    if ret_dict is None:
        return SuccessResult(detail=None)
    param_data_format = {}
    for param_name in ret_dict.keys():
        x_list = []
        y_list = []
        param_item = ret_dict.get(param_name)
        for key, value in param_item.items():
            """
            key 本来就是有序的，若无序，需排序
            """
            x_list.append(key)
            y_list.append(value)
        param_data_format[param_name] = [x_list, y_list]
    return SuccessResult(detail=param_data_format)


@gaolu_bp.route('/gaoluParamQuantile/', methods=['GET'])
def gaolu_param_quantile():
    start = request.args.get('start')
    end = request.args.get('end')
    refresh = request.args.get('refresh')
    ret = param_quantile_dict(start, end, refresh)
    return SuccessResult(detail=ret)


@gaolu_bp.route('/gaoluParamLoseStatus', methods=['GET'])
def gaolu_param_lose_status():
    start = request.args.get('start')
    end = request.args.get('end')
    display_item_num = request.args.get('display_item_num')
    status_list = gaolu_lose_status_percentage(start, end)
    ret = status_list[0:int(display_item_num)]
    ret.sort(key=lambda x: x[1], reverse=False)
    return SuccessResult(detail=ret)


@gaolu_bp.route('/autoScore', methods=['GET'])
def gaolu_auto_score():
    end = request.args.get('end')
    if end is None:
        end = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    end_time = datetime.datetime.strptime(end, "%Y-%m-%d %H:%M:%S")
    end_time = get_time_round_and_adjust(end_time, step=0, round_level='hour')
    start_time = get_time_round_and_adjust(end_time, step=-1, round_level='hour')
    ret = gaolu_biz_service.auto_score(start_time, end_time)
    return SuccessResult(detail=ret)


@gaolu_bp.route('/getDailyScore', methods=['GET'])
def gaolu_daily_score():
    date = request.args.get('date')
    date = datetime.datetime.strptime(date, "%Y-%m-%d %H:%M:%S")
    ret = get_daily_score(date)
    return SuccessResult(detail=ret)


@gaolu_bp.route('/getBanbieScore', methods=['GET'])
def gaolu_ban_bie_score():
    date = request.args.get('date')
    date = datetime.datetime.strptime(date, "%Y-%m-%d %H:%M:%S")
    ret = get_ban_bie_score(date)
    return SuccessResult(detail=ret)


@gaolu_bp.route('/modelQuery', methods=['GET'])
def gaolu_models_query():
    date = request.args.get('date')
    is_persist = request.args.get('is_persist')
    date = datetime.datetime.strptime(date, "%Y-%m-%d %H:%M:%S")
    gaolu_predict_po = gaolu_query_models(date, is_persist=is_persist)
    return SuccessResult(detail=gaolu_predict_po, encoder=GaoLuEncoder)


@gaolu_bp.route('/scoreTrend', methods=['GET'])
def gaolu_score_trend():
    start = request.args.get('start')
    end = request.args.get('end')
    if start is None or end is None:
        now = datetime.datetime.now()
        start_time = get_time_round_and_adjust(now, step=0, round_level='days')
        end_time = get_time_round_and_adjust(start_time, step=1, round_level='days')
    else:
        start_time = datetime.datetime.strptime(start, "%Y-%m-%d %H:%M:%S")
        end_time = datetime.datetime.strptime(end, "%Y-%m-%d %H:%M:%S")

    his_ret = get_gaolu_history_between(start_time, end_time, left="close", right="open",
                                        order_by=GaoLuPredictPO.DateTime.asc())
    date = []
    score = []
    for po in his_ret:
        date.append(po.DateTime.strftime("%Y-%m-%d %H:%M:%S"))
        score.append(po.CG_LT_GL_GL04_Score)
    ret = {
        'date': date,
        'score': score
    }
    return SuccessResult(detail=ret, encoder=GaoLuEncoder)


@gaolu_bp.route('/coreData', methods=['POST','GET'])
def gaolu_core_data():
    # start = request.args.get('start')
    # end = request.args.get('end')
    json_data = json.loads(request.get_data())
    start = json_data.get('start')
    end = json_data.get('end')
    params = json_data.get('params')

    if start is None or end is None:
        now = datetime.datetime.now()
        start_time = get_time_round_and_adjust(now, step=0, round_level='days')
        end_time = get_time_round_and_adjust(start_time, step=1, round_level='days')
    else:
        start_time = datetime.datetime.strptime(start, "%Y-%m-%d %H:%M:%S")
        end_time = datetime.datetime.strptime(end, "%Y-%m-%d %H:%M:%S")

    his_ret = get_gaolu_history_between(start_time, end_time, left="close", right="open",
                                        order_by=GaoLuPredictPO.DateTime.asc())
    ret = {}
    core_params = current_app.config['CORE_PARAMS'] if params is None else params +['DateTime']
    for param in core_params:
        ret[param] = []

    for po in his_ret:
        for param in core_params:
            ret[param].append(po.__getattribute__(param))
    return SuccessResult(detail=ret, encoder=GaoLuEncoder)


@gaolu_bp.route('/history', methods=['GET'])
def history():
    start = request.args.get('start')
    end = request.args.get('end')
    if start is None or end is None:
        start_time: datetime = datetime.datetime.now()
        end_time: datetime = get_time_round_and_adjust(start_time, step=1, round_level='days')
    else:
        start_time: datetime = datetime.datetime.strptime(start, "%Y-%m-%d %H:%M:%S")
        end_time: datetime = datetime.datetime.strptime(end, "%Y-%m-%d %H:%M:%S")

    his_ret: List[GaoLuPredictPO] = get_gaolu_history_between(start_time, end_time, left="open", right="close",
                                                              order_by=GaoLuPredictPO.DateTime.asc())

    for po in his_ret:
        attrs = po.__dir__()
        for attr in attrs:
            if re.search("^C", attr) and not re.search("status$", attr, re.IGNORECASE):
                if po.__getattribute__(attr) is None:
                    continue
                attr_value = str(round(po.__getattribute__(attr), 2))
                if attr + "_status" in attrs:
                    attr_value = attr_value + "(" + po.__getattribute__(attr + "_status") + ")"
                po.__setattr__(attr, attr_value)

    for gaolu_predict in his_ret:
        hour = gaolu_predict.FHour
        dt = gaolu_predict.DateTime
        if 0 <= hour <= 8:
            gaolu_predict.banbie = '夜班'
        if 9 <= hour <= 16:
            gaolu_predict.banbie = '白班'
        if 17 <= hour <= 23:
            gaolu_predict.banbie = '中班'

        base = datetime.datetime(2022,6,1)

        diff = (dt - base).days
        index = diff % 8
        index2 = (diff + 6) % 8
        index3 = (diff + 4) % 8
        index4 = (diff + 2) % 8
        r = ['中班', '中班', '休息', '夜班', '夜班', '休息', '白班', '白班']
        #banci_dict = {r[index]: '甲班', r[index2]: '乙班', r[index3]: '丙班', r[index4]: '丁班'}
        banci_dict = {r[index]: '丙班', r[index2]: '乙班', r[index3]: '甲班', r[index4]: '丁班'}
        gaolu_predict.banci = banci_dict[gaolu_predict.banbie]

        # fix datetime not continuous
        for gaolu_predict in his_ret:
            gmt_crete = get_time_round_and_adjust(gaolu_predict.GMT_CREATE, step=0, round_level='hour')
            if gaolu_predict.DateTime != gmt_crete:
                gaolu_predict.DateTime = gmt_crete

    return SuccessResult(detail=his_ret, encoder=GaoLuEncoder)


@gaolu_bp.route('/history/download', methods=['GET'])
def history_download():
    # 判断数据访问的类型
    start = request.args.get('start')
    end = request.args.get('end')
    if start is None or end is None:
        start_time: datetime = datetime.datetime.now()
        end_time: datetime = get_time_round_and_adjust(start_time, step=1, round_level='days')
    else:
        start_time: datetime = datetime.datetime.strptime(start, "%Y-%m-%d %H:%M:%S")
        end_time: datetime = datetime.datetime.strptime(end, "%Y-%m-%d %H:%M:%S")

    his_ret: List[GaoLuPredictPO] = get_gaolu_history_between(start_time, end_time, left="close", right="open",
                                                              order_by=GaoLuPredictPO.DateTime.asc())

    for gaolu_predict in his_ret:
        hour = gaolu_predict.FHour
        dt = gaolu_predict.DateTime
        if 0 <= hour < 8:
            gaolu_predict.banbie = '白班'
        if 8 <= hour < 16:
            gaolu_predict.banbie = '中班'
        if 16 <= hour < 23:
            gaolu_predict.banbie = '晚班'

        base = datetime.datetime(2022, 6, 1)

        diff = (dt - base).days
        index = diff % 8
        index2 = (diff + 6) % 8
        index3 = (diff + 4) % 8
        index4 = (diff + 2) % 8
        r = ['中班', '中班', '休息', '夜班', '夜班', '休息', '白班', '白班']
        banci_dict = {r[index]: '甲班', r[index2]: '乙班', r[index3]: '丙班', r[index4]: '丁班'}
        gaolu_predict.banci = banci_dict[gaolu_predict.banbie]

    # 文件下载

    import io
    import pandas as pd
    from flask import make_response, send_file

    ret_list = list()
    for gaolu_predict in his_ret:
        ordered = gaolu_history_data_transform(gaolu_predict)
        ret_list.append(ordered)

    data = pd.DataFrame(ret_list)

    out = io.BytesIO()
    writer = pd.ExcelWriter(out, engine='xlsxwriter')
    data.to_excel(excel_writer=writer, index=False, sheet_name='示例')
    writer.close()
    # go back to the beginning of the stream
    out.seek(0)
    response = make_response(
        send_file(out, attachment_filename=start + "至" + end + "历史数据.xlsx", as_attachment=True))
    return response

@gaolu_bp.route('/ruleDefinition/get', methods=['GET'])
def gaolu_rule_query():
    from app.models.po.gaolu.gaolu_rule import GaoLuRulePO

    rule_list = convert.query(GaoLuRulePO).all()
    return SuccessResult(detail=rule_list, encoder=GaoLuEncoder)
